package calc

import "fmt"

type NFARuleBook struct {
	rules []FARule
}

func NewNFARuleBook(rules []FARule) NFARuleBook {
	return NFARuleBook{
		rules,
	}
}

// 返回所有能通过自由移动到达的状态
func (book NFARuleBook) followFreeMoves(states []string) []string {
	moreStates := book.NextStates(states, "")
	// 如果 moreStates 是 states 的子集，则返回之，否则就将其加入到 states 中
	// TODO 这里判断要改
	if len(moreStates) == len(states) {
		return states
	} else {
		for _, moreState := range moreStates {
			var moreStateIn = false
			for _, state := range states {
				if state == moreState {
					moreStateIn = true
				}
			}
			if !moreStateIn {
				moreStates = append(states, moreStates...)
			}
			return moreStates
		}
	}

	return nil
}

// states 对应与 char 的可能的下一个状态集合 Set
func (book NFARuleBook) NextStates(states []string, char string) []string {
	var nextStates []string
	for _, state := range states {
		for _, ns := range book.FollowRulesFor(state, char) {
			var alreadyInSet = false
			for _, _ns := range nextStates {
				if _ns == ns {
					alreadyInSet = true
					break
				}
			}
			if !alreadyInSet {
				nextStates = append(nextStates, ns)
			}
		}
	}
	return nextStates
}

// 获取 state, char 输入后的结果集
func (book NFARuleBook) FollowRulesFor(state string, char string) []string {
	var followStates []string
	for _, rule := range book.RulesFor(state, char) {
		followStates = append(followStates, rule.Follow())
	}
	return followStates
}

// 获取适用于 state, char 的全部 rule
func (book NFARuleBook) RulesFor(state string, char string) []FARule {
	var rules []FARule
	for _, rule := range book.rules {
		if rule.AppliesTo(state, char) {
			rules = append(rules, rule)
		}
	}
	return rules
}

type NFA struct {
	currentStates []string
	acceptStates  []string
	rules         NFARuleBook
}

func NewNFA(currentStates []string, acceptStates []string, rules NFARuleBook) NFA {
	return NFA{
		currentStates,
		acceptStates,
		rules,
	}
}

// 当前状态是不是在可接受状态中
func (nfa NFA) IsAccepting() bool {
	for _, crtState := range nfa.currentStates {
		for _, acpState := range nfa.acceptStates {
			if crtState == acpState {
				return true
			}
		}
	}
	return false
}

func (nfa *NFA) ReadCharacter(char string) {
	nfa.currentStates = nfa.rules.NextStates(nfa.currentStates, char)
}

func (nfa *NFA) ReadString(str string) {
	for _, char := range str {
		nfa.ReadCharacter(fmt.Sprint(char))
	}
}

// 加上可以通过自由移动到达的状态
func (nfa *NFA) getCurrentStates() []string {
	return nil
}
